#include <fmt/ranges.h>
#include "../opengl/opengl.hpp"
#include "../gl/Camera.hpp"
#include "../gl/AxisHelper.hpp"
#include "../gl/Window.hpp"
#include "../gl/Model.hpp"
namespace gl = opengl;

int main() {
    Window window("OpenGL", 800, 600);
    gl::init_opengl(gl::opengl_config{.load_function = &SDL_GL_GetProcAddress,
                                      .debug_msg_callback = [](auto, auto, auto id, auto, auto, auto msg, auto) {
                                          //   fmt::println("[OpenGL Object {}] {}", id, msg);
                                      }});
    PerspectiveCamera camera;
    camera.set_position({-100.0f, 100.0f, 100.0f});
    camera.look_at(glm::vec3{0.0f});

    gl::buffer worldUBO(80); // binding = 0
    worldUBO.bind_to(gl::buffer::uniform_buffer, 0);
    AxisHelper helper(50.0f);
    Model::Model model("../model/spider/spider.obj");
    fmt::println("{}", model.program.get_error());
    window.on_exec = [&](auto) {
        auto [w, h] = window.get_size();
        gl::api::glViewport(0, 0, w, h);
        camera.set_aspect_ratio((float) w / (float) h);
        gl::api::glEnable(0x0B71); // GL_DEPTH_TEST
    };
    window.on_resize = [&](auto, int w, int h) {
        gl::api::glViewport(0, 0, w, h);
        camera.set_aspect_ratio((float) w / (float) h);
    };
    window.on_render = [&](auto) {
        gl::clear_buffers();
        // gl::api::glClear(0x0100);
        // World
        worldUBO.set_data(glm::value_ptr(camera.position), sizeof(glm::vec3));
        worldUBO.set_data(glm::value_ptr(camera.viewProjectionMatrix), sizeof(glm::mat4), 16);
        // Transform
        model.program.set_mat4f(3, glm::value_ptr(camera.viewProjectionMatrix));
        // Model
        // gl::api::glPolygonMode(0x0408, 0x1B01);
        model.render();
        helper.render();
    };
    window.on_process_event = [&](auto, const SDL_Event *event) {
        if (event->type == SDL_EventType::SDL_MOUSEWHEEL) {
            constexpr float sensitivity = 2.0f;
            auto fov = glm::clamp(camera.fov - sensitivity * event->wheel.preciseY, 15.0f, 85.0f);
            camera.set_fov(fov);
        } else if (event->type == SDL_EventType::SDL_KEYDOWN && event->key.keysym.sym == SDL_KeyCode::SDLK_ESCAPE) {
            window.exit(0);
        }
    };

    return window.exec();
}